// Copyright 2016 Proyectos y Sistemas de Mantenimiento SL (eProsima).
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ------------------------------------------------------------------
// Modification history:
// feature: Support static xml filter by participant name
// feature: add qos incompatible check, and add system test case
// ------------------------------------------------------------------

#include <ertps/xmlparser/XMLEndpointParser.h>

#include <ertps/utils/TimeConversion.h>
#include <ertps/utils/LocatorAlias.h>
#include <edds/rtps/builtin/data/WriterProxyData.h>
#include <edds/rtps/builtin/data/ReaderProxyData.h>

#include <tinyxml2.h>
#include <string>
#include <cstdlib>
#include <elog/Log.hpp>

using evbs::ertps::rtps::ReaderProxyData;
using evbs::ertps::rtps::WriterProxyData;
using vbsutil::xmlparser::ReaderProxyDataPart;
using vbsutil::xmlparser::StaticRTPSParticipantInfoPart;
using vbsutil::xmlparser::WriterProxyDataPart;
using vbsutil::xmlparser::XMLEndpointParserPart;
using vbsutil::xmlparser::XMLP_ret;

namespace evbs {
namespace ertps {
namespace xmlparser {

XMLEndpointParser::XMLEndpointParser() {
    // TODO(test) Auto-generated constructor stub
}

XMLEndpointParser::~XMLEndpointParser() {
    // TODO(test) Auto-generated destructor stub
    for (std::vector<StaticRTPSParticipantInfo*>::iterator pit = m_RTPSParticipants.begin();
         pit != m_RTPSParticipants.end(); ++pit) {
        for (std::vector<ReaderProxyData*>::iterator rit = (*pit)->m_readers.begin(); rit != (*pit)->m_readers.end();
             ++rit) {
            delete (*rit);
        }
        for (std::vector<WriterProxyData*>::iterator wit = (*pit)->m_writers.begin(); wit != (*pit)->m_writers.end();
             ++wit) {
            delete (*wit);
        }

        delete (*pit);
    }
}

void XMLEndpointParser::AssignParticipants(std::unique_ptr<vbsutil::xmlparser::XMLEndpointParserPart>&& edpxmlPtr) {
    // xmlparser库中解析的值回填至ertps
    for (std::vector<StaticRTPSParticipantInfoPart*>::iterator pit = (edpxmlPtr->getRTPSParticipantsInfo()).begin();
         pit != (edpxmlPtr->getRTPSParticipantsInfo()).end(); ++pit) {
        StaticRTPSParticipantInfo* pdata = new StaticRTPSParticipantInfo();

        pdata->m_RTPSParticipantName = (*pit)->m_RTPSParticipantName;
        for (std::vector<ReaderProxyDataPart*>::iterator rit = (*pit)->m_readers.begin();
             rit != (*pit)->m_readers.end(); ++rit) {
            ReaderProxyData* rdata =
                new ReaderProxyData((*rit)->unicast_locators_size, (*rit)->multicast_locators_size);
            rdata->userDefinedId((*rit)->userDefinedId());
            rdata->guid((*rit)->guid());
            rdata->topicName((*rit)->topicName());
            rdata->typeName((*rit)->typeName());
            rdata->topicKind((*rit)->topicKind());
            rdata->set_remotelocators((*rit)->remote_locators());
            rdata->m_qos = (*rit)->m_qos;

            pdata->m_readers.push_back(rdata);
        }
        for (std::vector<WriterProxyDataPart*>::iterator wit = (*pit)->m_writers.begin();
             wit != (*pit)->m_writers.end(); ++wit) {
            WriterProxyData* wdata =
                new WriterProxyData((*wit)->unicast_locators_size, (*wit)->multicast_locators_size);
            wdata->userDefinedId((*wit)->userDefinedId());
            wdata->guid((*wit)->guid());
            wdata->topicName((*wit)->topicName());
            wdata->typeName((*wit)->typeName());
            wdata->topicKind((*wit)->topicKind());
            wdata->set_remotelocators((*wit)->remote_locators());
            wdata->m_qos = (*wit)->m_qos;

            pdata->m_writers.push_back(wdata);
        }

        m_RTPSParticipants.push_back(pdata);
    }
}

XMLP_ret XMLEndpointParser::loadXMLFile(std::string& filename) {
    std::string temp = "";
    return loadXMLFile(filename, temp);
}

XMLP_ret XMLEndpointParser::loadXMLFile(std::string& filename, std::string& participantName) {
    std::unique_ptr<XMLEndpointParserPart> edpxmlPtr(new XMLEndpointParserPart());
    if (edpxmlPtr->loadXMLFile(filename, participantName) != XMLP_ret::XML_OK) {
        elogError(XMLPARSER, RetCode_t::RETCODE_ERROR, filename << " XML has errors");
        return XMLP_ret::XML_ERROR;
    }
    AssignParticipants(std::move(edpxmlPtr));
    return XMLP_ret::XML_OK;
}

XMLP_ret XMLEndpointParser::loadXMLNode(tinyxml2::XMLDocument& doc) {
    std::unique_ptr<XMLEndpointParserPart> edpxmlPtr(new XMLEndpointParserPart());
    if (edpxmlPtr->loadXMLNode(doc) != XMLP_ret::XML_OK) {
        return XMLP_ret::XML_ERROR;
    }
    AssignParticipants(std::move(edpxmlPtr));
    return XMLP_ret::XML_OK;
}

XMLP_ret XMLEndpointParser::lookforReader(const char* partname, uint16_t id, ReaderProxyData** rdataptr) {
    if (partname == nullptr) {
        return XMLP_ret::XML_ERROR;
    }
    for (std::vector<StaticRTPSParticipantInfo*>::iterator pit = m_RTPSParticipants.begin();
         pit != m_RTPSParticipants.end(); ++pit) {
        if ((*pit)->m_RTPSParticipantName == partname || true) {
            // it doenst matter the name fo the RTPSParticipant,
            // only for organizational purposes
            for (std::vector<ReaderProxyData*>::iterator rit = (*pit)->m_readers.begin();
                 rit != (*pit)->m_readers.end(); ++rit) {
                if ((*rit)->userDefinedId() == id) {
                    *rdataptr = *rit;
                    return XMLP_ret::XML_OK;
                }
            }
        }
    }
    return XMLP_ret::XML_ERROR;
}

XMLP_ret XMLEndpointParser::lookforWriter(const char* partname, uint16_t id, WriterProxyData** wdataptr) {
    for (std::vector<StaticRTPSParticipantInfo*>::iterator pit = m_RTPSParticipants.begin();
         pit != m_RTPSParticipants.end(); ++pit) {
        if ((partname && (*pit)->m_RTPSParticipantName == partname) ||
            true) {  // it doenst matter the name fo the RTPSParticipant, only for organizational
                     // purposes
            for (std::vector<WriterProxyData*>::iterator wit = (*pit)->m_writers.begin();
                 wit != (*pit)->m_writers.end(); ++wit) {
                if ((*wit)->userDefinedId() == id) {
                    *wdataptr = *wit;
                    return XMLP_ret::XML_OK;
                }
            }
        }
    }
    return XMLP_ret::XML_ERROR;
}

}  // namespace xmlparser
}  // namespace ertps
}  // namespace evbs
